package cnsatmsmart.automation.mmi.view.layers;

import com.bbn.openmap.LatLonPoint;
import com.bbn.openmap.Layer;
import com.bbn.openmap.MapBean;
import com.bbn.openmap.event.ProjectionEvent;
import com.bbn.openmap.omGraphics.OMCircle;
import com.bbn.openmap.omGraphics.OMGraphic;
import com.bbn.openmap.omGraphics.OMGraphicList;
import com.bbn.openmap.omGraphics.OMLine;
import com.bbn.openmap.omGraphics.OMTextLabeler;
import com.bbn.openmap.proj.Length;
import com.bbn.openmap.proj.Projection;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;

import cnsatmsmart.automation.mmi.helper.utilities.GlobalEnvVars;

/**
 * @author SIK - PTIK, BPPT
 **/

public class RadarLayer extends Layer implements Cloneable {
    /* const */
        private static final Color CENTER_COLOR = Color.YELLOW;
            //nilai warna default untuk pewarnaan pada penggambaran pusat radar
        private static final Color FIXES_COLOR = new Color (128, 225, 128);
            //nilai warna default untuk pewarnaan pada penggambaran radar yang merupakan instance dari kelas RadarLayer

    /* atribut - atribut yang dimiliki oleh kelas RadarLayer */
        private float latitude;     //posisi titik pusat radar pada garis lintang
        private float longitude;    //posisi titik pusat radar pada garis bujur
        private Color color;        //warna dari object radar
        
        private OMGraphicList graphics = new OMGraphicList();
        private Projection projection = null;
        private MapBean map;

        //enable / disable showing items
            private boolean drawCircularLabel = false;
            private boolean drawBigAngle = false;
            private boolean drawSmallAngle = false;

        float[] radarNM = new float[5];

    /* constructor - user defined ctor, no default ctor */
        // <editor-fold defaultstate="collapsed" desc="ctor">
        /*
         * @param = atribut
         */
        private RadarLayer (float lat, float lon, MapBean map) {
            this.latitude = lat;
            this.longitude = lon;
            this.color = FIXES_COLOR;
            this.map = map;
        }
        /**
         * menginstansiasi object RadarLayer dengan titik pusat radar berada pada posisi (lat, lon)
         * @param map MapBean
         * @param latDegrees int yang merupakan posisi derajat dari pusat radar dalam koordinat lintang
         * @param latMinutes int yang merupakan posisi menit dari pusat radar dalam koordinat lintang
         * @param latSeconds float yang merupakan posisi detik dari pusat radar dalam koordinat lintang
         * @param latSign char yang merupakan arah dari pusat radar dalam koordinat lintang {N, S}
         * @param lonDegrees int yang merupakan posisi derajat dari pusat radar dalam koordinat bujur
         * @param lonMinutes int yang merupakan posisi menit dari pusat radar dalam koordinat bujur
         * @param lonSeconds float yang merupakan posisi detik dari pusat radar dalam koordinat bujur
         * @param lonSign char yang merupakan arah dari pusat radar dalam koordinat bujur {W, E}
         */
        public RadarLayer(MapBean map, int latDegrees, int latMinutes, float latSeconds, char latSign, int lonDegrees, int lonMinutes, float lonSeconds, char lonSign) {
            this(0.0f, 0.0f, map);

            float radarCenterLat = this.latitude;
            float radarCenterLon = this.longitude;

            try {
                radarCenterLat = (latSign == 'N' ? 1.0f : -1.0f) * (latDegrees + (latMinutes / 60.0f) + (latSeconds / 3600.0f));
                radarCenterLon = (lonSign == 'E' ? 1.0f : -1.0f) * (lonDegrees + (lonMinutes / 60.0f) + (lonSeconds / 3600.0f));
            } catch (NumberFormatException nfexcpt) {
                radarCenterLat = this.latitude;
                radarCenterLon = this.longitude;
            } catch (Exception e) {
                radarCenterLat = this.latitude;
                radarCenterLon = this.longitude;
            }

            this.latitude = radarCenterLat;
            this.longitude = radarCenterLon;

            radarNM[0] = 50.0f; radarNM[1] = 100.0f; radarNM[2] = 150.0f; radarNM[3] = 200.0f; radarNM[4] = 250.0f;
        }
        // </editor-fold>

    /* setter */
        /**
         * memindahkan posisi dari pusat radar
         * @param lat float yang merupakan posisi baru dari pusat radar dalam koordinat lintang
         * @param lon float yang merupakan posisi baru dari pusat radar dalam koordinat bujur
         */
        public void setCenter(float lat, float lon) {                          //memindahkan posisi dari pusat radar
            /* I.S. sebarang */
            /* F.S. this.latitude terdefinisi dan bernilai sama dengan parameter lat DAN this.longitude terdefinisi dan bernilai sama dengan parameter lon */
            /* Proses : mengisikan dan mengubah nilai this.latitude DAN this.longitude dengan parameter lat DAN lon */
                this.latitude = lat;
                this.longitude = lon;
                repaint();
        }

    /* getter */
        /**
         * mendapatkan nilai dari posisi pusat radar saat ini
         * @return LatLonPoint yang merupakan posisi dari pusat radar saat ini dalam koordinat lintang bujur
         */
        public LatLonPoint getCenter() {                                       //mendapatkan nilai dari posisi pusat radar saat ini
            /* mengembalikan nilai dari atribut latitude dan longitude */
            return (new LatLonPoint(this.latitude, this.longitude));
        }
    
    /* method - method yang dimiliki oleh kelas RadarLayer */
        private OMGraphicList drawCenter (float lat, float lon) {               //menggambarkan pusat radar
            /* pusat lingkaran digambarkan dalam representasi + */
            //calculate center
                OMGraphicList omGs = new OMGraphicList();

            OMLine line1 = new OMLine(lat, lon, -3, 0, 3, 0);
            line1.setLinePaint(CENTER_COLOR);
            OMLine line2 = new OMLine(lat, lon, 0, -3, 0, 3);
            line2.setLinePaint(CENTER_COLOR);

            omGs.add(line1);
            omGs.add(line2);

            return (omGs);
        }
        private OMCircle drawCircle (float lat, float lon, float nm) {          //menggambarkan lingkaran radar
            //calculate center
                OMCircle circle = new OMCircle(lat, lon, nm, Length.NM);

            circle.setLinePaint(this.color);
        
            return (circle);
        }

        /* menggambar garis pembagi lingkaran radar dengan unit satuan pembagi 0.075 rad */
        private OMGraphicList drawBAngle (float lat, float lon, float rad) {    //menggambarkan garis yang menyatakan ukuran derajat besar radar
            float scale = this.map.getScale();
            float factor = 0.075f * (scale >= GlobalEnvVars.fullRadarScale2 ? 1 : (scale / GlobalEnvVars.fullRadarScale2));  //radian

            OMGraphicList omGs = new OMGraphicList();

            //0 degree
                OMLine line = new OMLine(lat + rad, lon, lat + (rad + factor), lon, OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);

            //180 degrees
                line = new OMLine(lat - rad, lon, lat - (rad + factor), lon, OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);

            //90 degrees
                line = new OMLine(lat, lon + rad, lat, lon  + (rad + factor), OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);

            //270 degrees
                line = new OMLine(lat, lon - rad, lat, lon  - (rad + factor), OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);

            float xChange = (GlobalEnvVars.COS45 * rad);
            float yChange = (GlobalEnvVars.SIN45 * rad);

            //45 degrees (may not correct)
                line = new OMLine(lat + xChange, lon + yChange, lat + (xChange + factor), lon  + (yChange + factor), OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);

            //135 degrees (may not correct)
                line = new OMLine(lat - xChange, lon + yChange, lat - (xChange + factor), lon  + (yChange + factor), OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);

            //225 degrees (may not correct)
                line = new OMLine(lat - xChange, lon - yChange, lat - (xChange + factor), lon  - (yChange + factor), OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);

            //315 degrees (may not correct)
                line = new OMLine(lat + xChange, lon - yChange, lat + (xChange + factor), lon  - (yChange + factor), OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);

            return (omGs);
        }
        private OMGraphicList drawSAngle (float lat, float lon, float rad) {    //menggambarkan garis yang menyatakan ukuran derajat kecil radar
            float scale = this.map.getScale();
            float factor = 0.0375f * (scale >= GlobalEnvVars.fullRadarScale2 ? 1 : (scale / GlobalEnvVars.fullRadarScale2));  //radian

            OMGraphicList omGs = new OMGraphicList();

            //15 degrees (may not correct)
                float xChange = (GlobalEnvVars.COS15 * rad);
                float yChange = (GlobalEnvVars.SIN15 * rad);

                float fx = (GlobalEnvVars.COS15 * factor);
                float fy = (GlobalEnvVars.SIN15 * factor);
                
                OMLine line = new OMLine(lat + xChange, lon + yChange, lat + (xChange + fx), lon  + (yChange + fy), OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);
                line = new OMLine(lat - xChange, lon + yChange, lat - (xChange + fx), lon  + (yChange + fy), OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);
                line = new OMLine(lat - xChange, lon - yChange, lat - (xChange + fx), lon  - (yChange + fy), OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);
                line = new OMLine(lat + xChange, lon - yChange, lat + (xChange + fx), lon  - (yChange + fy), OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);

            //30 degrees (may not correct)
                xChange = (GlobalEnvVars.COS30 * rad);
                yChange = (GlobalEnvVars.SIN30 * rad);

                fx = (GlobalEnvVars.COS30 * factor);
                fy = (GlobalEnvVars.SIN30 * factor);

                line = new OMLine(lat + xChange, lon + yChange, lat + (xChange + fx), lon  + (yChange + fy), OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);
                line = new OMLine(lat - xChange, lon + yChange, lat - (xChange + fx), lon  + (yChange + fy), OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);
                line = new OMLine(lat - xChange, lon - yChange, lat - (xChange + fx), lon  - (yChange + fy), OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);
                line = new OMLine(lat + xChange, lon - yChange, lat + (xChange + fx), lon  - (yChange + fy), OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);

            //60 degrees (may not correct)
                xChange = (GlobalEnvVars.COS60 * rad);
                yChange = (GlobalEnvVars.SIN60 * rad);

                fx = (GlobalEnvVars.COS60 * factor);
                fy = (GlobalEnvVars.SIN60 * factor);

                line = new OMLine(lat + xChange, lon + yChange, lat + (xChange + fx), lon  + (yChange + fy), OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);
                line = new OMLine(lat - xChange, lon + yChange, lat - (xChange + fx), lon  + (yChange + fy), OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);
                line = new OMLine(lat - xChange, lon - yChange, lat - (xChange + fx), lon  - (yChange + fy), OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);
                line = new OMLine(lat + xChange, lon - yChange, lat + (xChange + fx), lon  - (yChange + fy), OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);

            //75 degrees (may not correct)
                xChange = (GlobalEnvVars.COS75 * rad);
                yChange = (GlobalEnvVars.SIN75 * rad);

                fx = (GlobalEnvVars.COS75 * factor);
                fy = (GlobalEnvVars.SIN75 * factor);

                line = new OMLine(lat + xChange, lon + yChange, lat + (xChange + fx), lon  + (yChange + fy), OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);
                line = new OMLine(lat - xChange, lon + yChange, lat - (xChange + fx), lon  + (yChange + fy), OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);
                line = new OMLine(lat - xChange, lon - yChange, lat - (xChange + fx), lon  - (yChange + fy), OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);
                line = new OMLine(lat + xChange, lon - yChange, lat + (xChange + fx), lon  - (yChange + fy), OMGraphic.LINETYPE_STRAIGHT);
                line.setLinePaint(this.color);
                omGs.add(line);

            return (omGs);
        }

        private OMTextLabeler drawCircularLabel (float lat, float lon, float rad, float nm) {       //menggambarkan label yang mencantumkan jarak derajat radar
            String label = String.format("%dNM", (int)nm);

            OMTextLabeler tl = new OMTextLabeler(label);
            tl.setLinePaint(this.color);
            Point point = this.map.getProjection().forward(lat + rad, lon);
            point.y = point.y + 15;
            tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
            tl.setLocation(point);

            return (tl);
        }
        private void drawCircularAngleLabel (OMGraphicList omgl, float lat, float lon, float rad) { //menggambarkan label yang mencantumkan ukuran derajat memutari radar
            //0 degree
                int degree = 0;
                float radian = 0.0f;
                String label = String.format("%d°", degree);
                OMTextLabeler tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                Point point = this.map.getProjection().forward(lat + rad, lon);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);

            //90 degrees
                degree = 90;
                radian = 1.570796327f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat, lon + rad);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);

            //180 degrees
                degree = 180;
                radian = 3.141592654f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat - rad, lon);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);
            
            //270 degrees
                degree = 270;
                radian = 4.71238898f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat, lon - rad);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);

            float xChange = (GlobalEnvVars.COS45 * rad);
            float yChange = (GlobalEnvVars.SIN45 * rad);

            //45 degrees
                degree = 45;
                radian = 0.785398163f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat + xChange, lon + yChange);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);

            //135 degrees
                degree = 135;
                radian = 2.35619449f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat - xChange, lon + yChange);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);

            //225 degrees
                degree = 225;
                radian = 3.926990817f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat - xChange, lon - yChange);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);

            //315 degrees
                degree = 315;
                radian = 5.497787144f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat + xChange, lon - yChange);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);

            //15 degrees
                xChange = (GlobalEnvVars.COS15 * rad);
                yChange = (GlobalEnvVars.SIN15 * rad);
                
                degree = 15;
                radian = 0.261799388f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat + xChange, lon + yChange);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);
                
                degree = 165;
                radian = 2.879793266f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat - xChange, lon + yChange);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);

                degree = 195;
                radian = 3.403392041f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat - xChange, lon - yChange);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);

                degree = 345;
                radian = 6.021385919f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat + xChange, lon - yChange);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);

            //30 degrees
                xChange = (GlobalEnvVars.COS30 * rad);
                yChange = (GlobalEnvVars.SIN30 * rad);

                degree = 30;
                radian = 0.523598776f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat + xChange, lon + yChange);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);

                degree = 150;
                radian = 2.617993878f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat - xChange, lon + yChange);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);

                degree = 210;
                radian = 3.665191429f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat - xChange, lon - yChange);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);

                degree = 330;
                radian = 5.759586532f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat + xChange, lon - yChange);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);

            //60 degrees
                xChange = (GlobalEnvVars.COS60 * rad);
                yChange = (GlobalEnvVars.SIN60 * rad);

                degree = 60;
                radian = 1.047197551f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat + xChange, lon + yChange);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);

                degree = 120;
                radian = 2.094395102f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat - xChange, lon + yChange);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);

                degree = 240;
                radian = 4.188790205f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat - xChange, lon - yChange);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);

                degree = 300;
                radian = 5.235987756f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat + xChange, lon - yChange);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);

            //75 degrees
                xChange = (GlobalEnvVars.COS75 * rad);
                yChange = (GlobalEnvVars.SIN75 * rad);

                degree = 75;
                radian = 1.308996939f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat + xChange, lon + yChange);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);

                degree = 105;
                radian = 1.832595715f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat - xChange, lon + yChange);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);

                degree = 255;
                radian = 4.450589593f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat - xChange, lon - yChange);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);

                degree = 285;
                radian = 4.974188368f;
                label = String.format("%d°", degree);
                tl = new OMTextLabeler(label);
                tl.setLinePaint(this.color);
                point = this.map.getProjection().forward(lat + xChange, lon - yChange);
                tl.setJustify(OMTextLabeler.JUSTIFY_CENTER);
                tl.setLocation(point);
                tl.setRotationAngle(radian);
                omgl.addOMGraphic(tl);
        }

        private OMGraphicList createGraphics (OMGraphicList graphics) {         //menggambarkan keseluruhan radar
            graphics.clear();

            graphics.addOMGraphic(drawCenter(this.latitude, this.longitude));
            
            createRadar(graphics, this.latitude, this.longitude);

            return (graphics);
        }
        private void createRadar (OMGraphicList omgl, float lat, float lon) {           //menggambarkan keseluruhan lingkaran radar
            float scale = this.map.getScale();
            if (scale >= GlobalEnvVars.fullRadarScale2) {
                for (int i = 0; i < 5; ++i) {
                    createRadar(omgl, lat, lon, radarNM[i]);
                }

                OMCircle circle = drawCircle(lat, lon, radarNM[4]);
                if (drawCircularLabel) {
                    drawCircularAngleLabel(omgl, lat, lon, (circle.getRadius() + 0.5f));
                }
            } else {
                for (int i = 0; i < 5; ++i) {
                    createRadar(omgl, lat, lon, (scale / GlobalEnvVars.fullRadarScale2 * radarNM[i]));
                }

                OMCircle circle = drawCircle(lat, lon, (scale / GlobalEnvVars.fullRadarScale2 * radarNM[4]));
                if (drawCircularLabel) {
                    drawCircularAngleLabel(omgl, lat, lon, (circle.getRadius() + (scale / GlobalEnvVars.fullRadarScale2 * 0.5f)));
                }
            }
        }
        private void createRadar (OMGraphicList omgl, float lat, float lon, float nm) { //menggambarkan lingkaran radar beserta pelabelannya
            OMCircle circle = drawCircle(lat, lon, nm);
            omgl.addOMGraphic(circle);
            if (drawCircularLabel) {    //menuliskan label dengan teks berupa nmNM
                omgl.addOMGraphic(drawCircularLabel(lat, lon, circle.getRadius(), nm));
            }
            if (drawBigAngle) {         //menggambarkan pembagian sudut yang lebih besar
                omgl.addOMGraphic(drawBAngle(lat, lon, circle.getRadius()));
            }
            if (drawSmallAngle) {       //menggambarkan pembagian sudut yang lebih kecil
                omgl.addOMGraphic(drawSAngle(lat, lon, circle.getRadius()));
            }
        }

    /**
     * event handler untuk event perubahan projection
     * @param pe ProjectionEvent event projection yang terjadi
     */
    public void projectionChanged(ProjectionEvent pe) {
        this.projection = (Projection) pe.getProjection().makeClone();
        repaint();
    }

    @Override
    public void paint (Graphics g) {
        drawCircularLabel = false;
        drawBigAngle = false;
        drawSmallAngle = false;

        float scale = this.map.getScale();

        if (scale <= 16000000f) {
            drawBigAngle = true;
        }
        if (scale <= 15000000f) {
            drawSmallAngle = true;
        }
        if (scale <= 13000000f) {
            drawCircularLabel = true;
        }

        createGraphics(this.graphics);
        this.graphics.project(this.projection, true);
        this.graphics.render(g);
    }

    @Override
    public Object clone () {
        try {
            RadarLayer cloned = (RadarLayer) super.clone();
            cloned.graphics = (OMGraphicList) this.graphics.clone();
            return (cloned);
        } catch (CloneNotSupportedException e) {
            System.out.println("RadarLayer.clone : CloneNotSupportedException " + e.getMessage());
            return (null);
        }
    }
}
